package com.zh.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zh.common.ErrorCode;
import com.zh.constant.PriorityConstant;
import com.zh.constant.RequirementConstant;
import com.zh.constant.TaskConstant;
import com.zh.domain.Model.AttachCount;
import com.zh.domain.dto.requirement.AddRequirementRequest;
import com.zh.domain.dto.requirement.PageReqDynamicRequest;
import com.zh.domain.dto.requirement.UpdateRequirementRequest;
import com.zh.domain.entity.*;
import com.zh.domain.vo.requirement.ReqDynamicVo;
import com.zh.domain.vo.requirement.RequirementVo;
import com.zh.domain.vo.task.TaskVo;
import com.zh.domain.vo.user.UserVO;
import com.zh.exception.ThrowUtils;
import com.zh.job.TaskManager;
import com.zh.mapper.AttachesMapper;
import com.zh.service.*;
import com.zh.mapper.RequirementsMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.framework.AopContext;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author Administrator
 * @description 针对表【requirements(需求表)】的数据库操作Service实现
 * @createDate 2025-02-09 16:24:10
 */
@Service
@Slf4j
public class RequirementsServiceImpl extends ServiceImpl<RequirementsMapper, Requirements>
        implements RequirementsService {
    @Resource
    private RequirementsMapper requirementsMapper;
    @Resource
    private ProjectService projectService;
    @Resource
    private ProjectUserService projectUserService;
    @Resource
    private ProjectDynamicsService projectDynamicsService;
    @Resource
    private UserService userService;
    @Resource
    private MessageService messageService;
    @Resource
    private TaskService taskService;
    @Resource
    @Lazy
    private MilestoneService milestoneService;
    @Resource
    @Lazy
    private IterationService iterationService;
    @Resource
    @Lazy
    private RequirementDynamicsService requirementDynamicsService;
    @Resource
    @Lazy
    private AttachesMapper attachesMapper;

    @Override
    @Transactional
    public Boolean addRequirement(AddRequirementRequest addRequirementRequest) {
        int loginId = StpUtil.getLoginIdAsInt();

        //1.参数校验
        Integer proId = addRequirementRequest.getProId();
        Integer mileId = addRequirementRequest.getMileId();
        Integer iterId = addRequirementRequest.getIterId();
        Integer ownerId = addRequirementRequest.getOwnerId();
        Integer priority = addRequirementRequest.getPriority();
        String title = addRequirementRequest.getTitle();
        String description = addRequirementRequest.getDescription();
        String remark = addRequirementRequest.getRemark();
        String tag = addRequirementRequest.getTag();
        ThrowUtils.throwIf(null == proId, ErrorCode.PARAMS_ERROR, "项目id不能为空");
        ThrowUtils.throwIf(!PriorityConstant.validPriority(priority), ErrorCode.PARAMS_ERROR, "错误的优先级");
        ThrowUtils.throwIf(null == ownerId, ErrorCode.PARAMS_ERROR, "负责人id不能为空");
        ThrowUtils.throwIf(null == title || title.length() > 100, ErrorCode.PARAMS_ERROR, "标题字数<100");
        //2.获取编号 编号规则 R-proId-count 插入requirements表
        LambdaQueryWrapper<Requirements> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Requirements::getProId, proId);
        Long count = requirementsMapper.selectCount(queryWrapper);
        Requirements requirements = BeanUtil.copyProperties(addRequirementRequest, Requirements.class);
        requirements.setCreateBy(loginId);
        requirements.setUpdateBy(loginId);
        requirements.setCode("R-" + "P" + proId + "-" + "M" + mileId + "-" + "I" + iterId + "-" + count + 1);
        requirements.setCreateAt(LocalDateTime.now());
        requirements.setUpdateAt(LocalDateTime.now());
        requirements.setStatus(0);
        boolean b = requirementsMapper.insert(requirements) > 0;
        //3.插入项目动态表
        sendMessageAndDynamicWhenAdd(loginId, requirements);
        return b;
    }

    @Override
    @Transactional
    public void sendMessageAndDynamicWhenAdd(Integer creatorId, Requirements requirements) {
        UserVO creator = userService.getUserVoById(creatorId);
        Integer ownerId = requirements.getOwnerId();
        UserVO receiver = userService.getUserVoById(ownerId);
        ProjectDynamics dynamics = new ProjectDynamics(true);
        dynamics.setProId(requirements.getProId());
        String content;
        content = creator.getName() + "指派了需求" + requirements.getTitle() + "-" + requirements.getCode() + " 给 " + receiver.getName();
        dynamics.setContent(content);
        projectDynamicsService.save(dynamics);
        //发送消息
        LambdaQueryWrapper<ProjectUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ProjectUser::getProId, requirements.getProId());
        List<ProjectUser> projectUserList = projectUserService.list(queryWrapper);
        List<Integer> userIdList = projectUserList.stream().map(ProjectUser::getUserId).collect(Collectors.toList());
        Project project = projectService.getById(requirements.getProId());
        Message message = new Message();
        String messageContent = project.getTitle() + "-" + creator.getName() +
                " 指派了需求-" +
                requirements.getTitle() +
                "-" +
                requirements.getCode() +
                " 给你";
        message.setContent(messageContent);
        message.setSendId(creatorId);
        message.setCreateAt(LocalDateTime.now());
        message.setCreateBy(creatorId);
        message.setUpdateAt(LocalDateTime.now());
        message.setUpdateBy(creatorId);
        message.setNoticeType(0);
        message.setType(2);
        Map<String, Object> paramsToOwner = new HashMap<>();
        paramsToOwner.put("reqId", Optional.ofNullable(requirements.getId()).map(Object::toString).orElse(null));
        paramsToOwner.put("proId", Optional.ofNullable(requirements.getProId()).map(Object::toString).orElse(null));
        paramsToOwner.put("milestoneId", Optional.ofNullable(requirements.getMileId()).map(Object::toString).orElse(null));
        paramsToOwner.put("iterId", Optional.ofNullable(requirements.getIterId()).map(Object::toString).orElse(null));
        paramsToOwner.put("payloadType", "requirement");
        paramsToOwner.put("title", requirements.getTitle());
        message.setParams(paramsToOwner);
        message.setStatus(1);
        message.setDeleted(0);
        messageService.sendMessage(message, userIdList);
    }

    @Override
    public List<RequirementVo> listByIterationId(Integer iterId) {
        if (iterId == null) {
            return new ArrayList<>();
        }
        LambdaQueryWrapper<Requirements> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Requirements::getIterId, iterId)
                .eq(Requirements::getDeleted, 0)
                .orderByAsc(Requirements::getId)
                .orderByAsc(Requirements::getStartTime)
                .orderByAsc(Requirements::getEndTime)
                .orderByAsc(Requirements::getPriority)
                .orderByAsc(Requirements::getStatus)
                .orderByAsc(Requirements::getCreateAt)
                .orderByAsc(Requirements::getUpdateAt);
        List<Requirements> requirementsList = requirementsMapper.selectList(queryWrapper);
        //获取附件数量
        List<Integer> reqIdList = requirementsList.stream().map(Requirements::getId).collect(Collectors.toList());
        List<AttachCount> attachCounts = new ArrayList<>();
        Map<Integer, AttachCount> reqAttachCountMap = new HashMap<>();
        if (!reqIdList.isEmpty()) {
            attachCounts = attachesMapper.countByReqIdList(reqIdList);
        }
        if (!attachCounts.isEmpty()) {
            attachCounts.forEach(attachCount -> reqAttachCountMap.put(attachCount.getTypeId(), attachCount));
        }
        //获取用户信息
        List<Integer> userIdList = requirementsList.stream()
                .flatMap(requirements -> Stream.of(requirements.getOwnerId(), requirements.getCreateBy(), requirements.getUpdateBy()))
                .filter(Objects::nonNull)
                .distinct()
                .collect(Collectors.toList());
        Map<Integer, UserVO> userVOMap = userService.listUserVoByIds(userIdList).stream()
                .collect(Collectors.toMap(UserVO::getId, userVO -> userVO));
        return requirementsList.stream().map(requirements -> {
            RequirementVo requirementVo = BeanUtil.copyProperties(requirements, RequirementVo.class);
            List<TaskVo> taskVoList = taskService.listByReqId(requirements.getId());
            requirementVo.setTaskVoList(taskVoList);
            requirementVo.setOwner(userVOMap.get(requirements.getOwnerId()));
            requirementVo.setCreator(userVOMap.get(requirements.getCreateBy()));
            requirementVo.setUpdater(userVOMap.get(requirements.getUpdateBy()));
            AttachCount attachCount = reqAttachCountMap.get(requirements.getId());
            requirementVo.setAttachCount(attachCount != null ? attachCount.getCount() : 0);
            return requirementVo;
        }).collect(Collectors.toList());
    }

    @Override
    @Transactional
    public Boolean updateRequirement(UpdateRequirementRequest updateRequirementRequest) {
        Integer loginId = StpUtil.getLoginIdAsInt();
        return updateRequirement(loginId, updateRequirementRequest);
    }

    @Override
    @Transactional
    public Boolean updateRequirement(Integer userId, UpdateRequirementRequest updateRequirementRequest) {
        RequirementsService proxy = (RequirementsService) AopContext.currentProxy();
        Integer loginId = userId;
        //1. 校验参数
        Integer id = updateRequirementRequest.getId();
        Integer iterId = updateRequirementRequest.getIterId();
        Integer mileId = updateRequirementRequest.getMileId();
        Integer status = updateRequirementRequest.getStatus();
        Integer ownerId = updateRequirementRequest.getOwnerId();
        String title = updateRequirementRequest.getTitle();
        String description = updateRequirementRequest.getDescription();
        String remark = updateRequirementRequest.getRemark();
        Integer priority = updateRequirementRequest.getPriority();
        LocalDateTime startTime = updateRequirementRequest.getStartTime();
        LocalDateTime endTime = updateRequirementRequest.getEndTime();
        ThrowUtils.throwIf(startTime != null && endTime != null && startTime.isAfter(endTime), ErrorCode.PARAMS_ERROR);
        ThrowUtils.throwIf(null == id, ErrorCode.PARAMS_ERROR);
        ThrowUtils.throwIf(null != status && !RequirementConstant.isValidStatus(status), ErrorCode.PARAMS_ERROR);
        ThrowUtils.throwIf(null != ownerId && ownerId < 0, ErrorCode.PARAMS_ERROR);
        ThrowUtils.throwIf(null != priority && !PriorityConstant.validPriority(priority), ErrorCode.PARAMS_ERROR);
        Requirements updateRequirement = new Requirements();
        synchronized (id) {
            Requirements oldRequirement = proxy.getById(id);
            LambdaUpdateWrapper<Requirements> updateWrapper = new LambdaUpdateWrapper<>();
            if (mileId != null && mileId != -1) {
                updateWrapper.set(Requirements::getMileId, mileId);
            } else if (mileId == null) {
                updateWrapper.set(Requirements::getMileId, null);
            }

            if (iterId != null && iterId != -1) {
                updateWrapper.set(Requirements::getIterId, iterId);
            } else if (iterId == null) {
                updateWrapper.set(Requirements::getIterId, null);
            }
            updateWrapper.eq(Requirements::getId, id)
                    .set(null != status, Requirements::getStatus, status)
                    .set(null != ownerId, Requirements::getOwnerId, ownerId)
                    .set(StrUtil.isNotEmpty(title), Requirements::getTitle, title)
                    .set(StrUtil.isNotEmpty(description), Requirements::getDescription, description)
                    .set(StrUtil.isNotEmpty(remark), Requirements::getRemark, remark)
                    .set(null != priority, Requirements::getPriority, priority)
                    .set(null != startTime, Requirements::getStartTime, startTime)
                    .set(null != endTime, Requirements::getEndTime, endTime)
                    .set(status != null && 4 == status, Requirements::getCompleteTime, LocalDateTime.now())
                    .set(Requirements::getUpdateAt, LocalDateTime.now())
                    .set(Requirements::getUpdateBy, loginId);
            boolean success = requirementsMapper.update(updateRequirement, updateWrapper) > 0;
            //若有关联的任务,则一并更新任务的关联里程碑和迭代
            if (success) {
                List<TaskVo> taskList = taskService.listByReqId(id);
                List<Task> updateTaskList = taskList.stream().map(taskVo -> {
                    Task task = BeanUtil.copyProperties(taskVo, Task.class);
                    if (null != iterId && iterId != -1) {
                        task.setIterId(iterId);
                    } else if (iterId == null) {
                        task.setIterId(null);
                    }

                    if (null != mileId && mileId != -1) {
                        task.setMileId(mileId);
                    } else if (mileId == null) {
                        task.setMileId(null);
                    }
                    return task;
                }).collect(Collectors.toList());
                taskService.updateBatchById(updateTaskList);
            }
            //3.更新数据
            Requirements updatedRequirement = proxy.getById(id);
            //4. 发送消息、动态、触发更新项目、里程碑、迭代、需求服务
            if (success) {
                TaskManager.execute(() -> sendMessageAndDynamicWhenUpdate(loginId, oldRequirement, updatedRequirement));
            }
            return success;
        }
    }

    @Override
    @Transactional
    public void sendMessageAndDynamicWhenUpdate(Integer operatorId, Requirements oldRequirement, Requirements newRequirement) {
        Integer updateBy = newRequirement.getUpdateBy();
        UserVO updater = userService.getUserVoById(updateBy);
        ProjectDynamics templateDynamics = new ProjectDynamics(true);
        templateDynamics.setProId(newRequirement.getProId());
        templateDynamics.setCreateBy(operatorId);
        templateDynamics.setUpdateBy(operatorId);
        List<ProjectDynamics> projectDynamicsList = new ArrayList<>();
        List<RequirementDynamics> requirementDynamicsList = new ArrayList<>();
        List<String> contentList = new ArrayList<>();
        generateDynamicContent(oldRequirement, newRequirement, contentList, updater);
        contentList.forEach(dynamicContent -> {
            ProjectDynamics dynamics = BeanUtil.copyProperties(templateDynamics, ProjectDynamics.class);
            dynamics.setContent(dynamicContent);
            projectDynamicsList.add(dynamics);
            RequirementDynamics requirementDynamics = new RequirementDynamics();
            requirementDynamics.setReqId(newRequirement.getId());
            requirementDynamics.setContent(dynamicContent);
            requirementDynamics.setCreateAt(LocalDateTime.now());
            requirementDynamics.setCreateBy(operatorId);
            requirementDynamics.setUpdateAt(LocalDateTime.now());
            requirementDynamics.setUpdateBy(operatorId);
            requirementDynamics.setStatus(1);
            requirementDynamics.setDeleted(0);
            requirementDynamicsList.add(requirementDynamics);
        });
        projectDynamicsService.saveBatch(projectDynamicsList);
        requirementDynamicsService.saveBatch(requirementDynamicsList);
        // 切换了负责人发送消息
        if (!Objects.equals(oldRequirement.getOwnerId(), newRequirement.getOwnerId())) {
            UserVO oldOwner = userService.getUserVoById(oldRequirement.getOwnerId());
            UserVO newOwner = userService.getUserVoById(newRequirement.getOwnerId());
            Message messageToOldOwner = new Message();
            //发送给旧负责人
            String messageContent = updater.getName() +
                    " 将你负责的需求 " +
                    newRequirement.getTitle() +
                    "移交给 " +
                    newOwner.getName();
            messageToOldOwner.setContent(messageContent);
            messageToOldOwner.setSendId(updater.getId());
            messageToOldOwner.setCreateAt(LocalDateTime.now());
            messageToOldOwner.setCreateBy(operatorId);
            messageToOldOwner.setUpdateAt(LocalDateTime.now());
            messageToOldOwner.setUpdateBy(operatorId);
            messageToOldOwner.setNoticeType(0);
            messageToOldOwner.setType(3);
            Map<String, Object> params = new HashMap<>();
            params.put("reqId", Optional.ofNullable(newRequirement.getId()).map(Object::toString).orElse(null));
            params.put("proId", Optional.ofNullable(newRequirement.getProId()).map(Object::toString).orElse(null));
            params.put("iterId", Optional.ofNullable(newRequirement.getIterId()).map(Object::toString).orElse(null));
            params.put("milestoneId", Optional.ofNullable(newRequirement.getMileId()).map(Object::toString).orElse(null));
            params.put("payloadType", "requirement");
            params.put("title", newRequirement.getTitle());
            messageToOldOwner.setParams(params);
            messageToOldOwner.setStatus(1);
            messageToOldOwner.setDeleted(0);
            messageService.sendMessage(messageToOldOwner, List.of(oldOwner.getId()));
            // 发送给新负责人
            Message messageToNewOwner = new Message();
            String messageContent1 = updater.getName() +
                    " 为你分配了需求 " +
                    newRequirement.getTitle() +
                    ",请及时处理.";
            messageToNewOwner.setContent(messageContent1);
            messageToNewOwner.setSendId(updater.getId());
            messageToNewOwner.setCreateAt(LocalDateTime.now());
            messageToNewOwner.setCreateBy(operatorId);
            messageToNewOwner.setUpdateAt(LocalDateTime.now());
            messageToNewOwner.setUpdateBy(operatorId);
            messageToNewOwner.setNoticeType(0);
            messageToNewOwner.setType(3);
            messageToNewOwner.setParams(params);
            messageToNewOwner.setStatus(1);
            messageToNewOwner.setDeleted(0);
            messageService.sendMessage(messageToNewOwner, List.of(newOwner.getId()));
        }
    }

    private void generateDynamicContent(Requirements oldRequirement, Requirements newRequirement, List<String> contentList, UserVO updater) {
        String content;
        if (!Objects.equals(oldRequirement.getMileId(), newRequirement.getMileId())) {
            Milestone oldMilestone = milestoneService.getById(oldRequirement.getMileId());
            Milestone newMilestone = milestoneService.getById(newRequirement.getMileId());
            content = updater.getName() + "将需求 " + newRequirement.getTitle() + "从" + oldMilestone.getTitle() + " 移动到里程碑 " + newMilestone.getTitle() + '.';
            contentList.add(content);
        }
        if (!Objects.equals(oldRequirement.getOwnerId(), newRequirement.getOwnerId())) {
            UserVO oldOwner = userService.getUserVoById(oldRequirement.getOwnerId());
            UserVO newOwner = userService.getUserVoById(newRequirement.getOwnerId());
            content = updater.getName() + "将需求 " + newRequirement.getTitle() + "负责人从 " + oldOwner.getName() + " 切换为 " + newOwner.getName() + '.';
            contentList.add(content);
        }
        if (!Objects.equals(oldRequirement.getStatus(), newRequirement.getStatus())) {
            content = updater.getName() + "将需求 " + newRequirement.getTitle() + "状态从" + TaskConstant.getStatusName(oldRequirement.getStatus()) + " 切换为 " + TaskConstant.getStatusName(newRequirement.getStatus()) + '.';
            contentList.add(content);
        }
        if (!Objects.equals(oldRequirement.getPriority(), newRequirement.getPriority())) {
            content = updater.getName() + "将需求 " + newRequirement.getTitle() + "优先级从" + PriorityConstant.getPriorityName(oldRequirement.getPriority()) + " 切换为 " + PriorityConstant.getPriorityName(newRequirement.getPriority()) + '.';
            contentList.add(content);
        }
        if (!Objects.equals(oldRequirement.getTitle(), newRequirement.getTitle())) {
            content = updater.getName() + "将需求标题从 " + oldRequirement.getTitle() + " 修改为 " + newRequirement.getTitle() + '.';
            contentList.add(content);
        }
        if (!Objects.equals(oldRequirement.getMileId(), newRequirement.getMileId())) {
            Milestone oldMilestone = milestoneService.getById(oldRequirement.getMileId());
            Milestone newMilestone = milestoneService.getById(newRequirement.getMileId());
            content = updater.getName() + "将需求 " + newRequirement.getTitle() + "从迭代 " + oldMilestone.getTitle() + " 移动到里程碑 " + newMilestone.getTitle() + '.';
            contentList.add(content);
        }
        if (!Objects.equals(oldRequirement.getIterId(), newRequirement.getIterId())) {
            Iteration oldIteration = iterationService.getById(oldRequirement.getIterId());
            Iteration newIteration = iterationService.getById(newRequirement.getIterId());
            content = updater.getName() + "将需求 " + newRequirement.getTitle() + "从迭代 " + oldIteration.getTitle() + " 移动到迭代 " + newIteration.getTitle() + '.';
            contentList.add(content);
        }
        LocalDateTime oleStartTime = oldRequirement.getStartTime();
        LocalDateTime newStartTime = newRequirement.getStartTime();
        if (!Objects.equals(oleStartTime, newStartTime)) {
            //格式化时间
            String oldStartTimeStr = oldRequirement.getStartTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
            String newStartTimeStr = newRequirement.getStartTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
            content = updater.getName() + "将需求 " + newRequirement.getTitle() + " 开始时间从 " + oldStartTimeStr + " 修改为 " + newStartTimeStr + '.';
            contentList.add(content);
        }
        LocalDateTime oleEndTime = oldRequirement.getEndTime();
        LocalDateTime newEndTime = newRequirement.getEndTime();
        if (!Objects.equals(oleEndTime, newEndTime)) {
            String oldEndTimeStr = oldRequirement.getEndTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
            String newEndTimeStr = newRequirement.getEndTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
            content = updater.getName() + "将需求 " + newRequirement.getTitle() + " 结束时间从 " + oldEndTimeStr + " 修改为 " + newEndTimeStr + '.';
            contentList.add(content);
        }
        if (!Objects.equals(oldRequirement.getDescription(), newRequirement.getDescription())) {
            content = updater.getName() + "修改了需求 " + newRequirement.getTitle() + " 描述.";
            contentList.add(content);
        }
        if (!Objects.equals(oldRequirement.getRemark(), newRequirement.getRemark())) {
            content = updater.getName() + "修改了需求 " + newRequirement.getTitle() + " 备注.";
            contentList.add(content);
        }
    }

    @Override
    public RequirementVo getDetail(Integer id) {
        //1. 参数校验
        ThrowUtils.throwIf(null == id, ErrorCode.PARAMS_ERROR);
        Requirements requirements = requirementsMapper.selectById(id);
        if (Objects.isNull(requirements)) {
            return null;
        }
        RequirementVo requirementVo = BeanUtil.copyProperties(requirements, RequirementVo.class);
        UserVO creator = userService.getUserVoById(requirements.getCreateBy());
        UserVO owner = userService.getUserVoById(requirements.getOwnerId());
        UserVO updater = userService.getUserVoById(requirements.getUpdateBy());
        List<TaskVo> taskVos = taskService.listByReqId(id);
        requirementVo.setCreator(creator);
        requirementVo.setOwner(owner);
        requirementVo.setUpdater(updater);
        requirementVo.setTaskVoList(taskVos);
        return requirementVo;
    }

    @Override
    public RequirementVo getByTaskId(Integer taskId) {
        //1. 参数校验
        ThrowUtils.throwIf(null == taskId, ErrorCode.PARAMS_ERROR);
        Task task = taskService.getById(taskId);
        if (Objects.isNull(task)) {
            return null;
        }
        Integer reqId = task.getReqId();
        return getDetail(reqId);
    }

    @Override
    @Transactional
    public void updateProcessById(Integer id) {
        //1.获取所有关联任务
        List<TaskVo> taskVos = taskService.listByReqId(id);
        if (CollectionUtil.isEmpty(taskVos)) {
            return;
        }
        //2.已完成的任务数量/总任务数量 保留两位小数
        long completeCount = taskVos.stream().filter(taskVo -> taskVo.getStatus() == 4).count();
        BigDecimal progress = new BigDecimal(completeCount).divide(new BigDecimal(taskVos.size()), 2, RoundingMode.HALF_UP);
        //3.更新需求进度 若需求进度为100%，则更新需求状态为已完成
        Requirements requirements = new Requirements();
        if (progress.compareTo(BigDecimal.valueOf(1)) == 0) {
            requirements.setStatus(4);
            requirements.setCompleteTime(LocalDateTime.now());
        }
        requirements.setId(id);
        requirements.setProgress(progress);
        requirements.setUpdateAt(LocalDateTime.now());
        requirementsMapper.updateById(requirements);
        log.info("更新需求-{}-进度-{}", requirements.getId(), progress);
    }

    @Override
    public Page<ReqDynamicVo> pageDynamics(PageReqDynamicRequest pageReqDynamicRequest) {
        //1. 参数校验
        Integer reqId = pageReqDynamicRequest.getReqId();
        ThrowUtils.throwIf(null == reqId, ErrorCode.PARAMS_ERROR);
        pageReqDynamicRequest.standardizeSize();

        Integer current = pageReqDynamicRequest.getCurrent();
        Integer pageSize = pageReqDynamicRequest.getPageSize();
        Page<RequirementDynamics> page = new Page<>(current, pageSize);
        LambdaQueryWrapper<RequirementDynamics> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(RequirementDynamics::getReqId, reqId)
                .orderByDesc(RequirementDynamics::getCreateAt)
                .orderByDesc(RequirementDynamics::getId);
        Page<RequirementDynamics> requirementDynamicsPage = requirementDynamicsService.page(page, queryWrapper);
        List<RequirementDynamics> records = requirementDynamicsPage.getRecords();
        //2.获取用户数据
        if (records.isEmpty()) {
            return new Page<>();
        }
        List<Integer> userIdList = records.stream()
                .flatMap(taskDynamics -> Stream.of(taskDynamics.getCreateBy()))
                .filter(Objects::nonNull)
                .distinct()
                .collect(Collectors.toList());
        List<UserVO> userVOList = userService.listUserVoByIds(userIdList);
        Map<Integer, UserVO> userVOMap = userVOList.stream().collect(Collectors.toMap(UserVO::getId, userVO -> userVO));
        List<ReqDynamicVo> resultList = new ArrayList<>();
        for (RequirementDynamics requirementDynamics : records) {
            ReqDynamicVo reqDynamicVo = BeanUtil.copyProperties(requirementDynamics, ReqDynamicVo.class);
            reqDynamicVo.setCreator(userVOMap.get(requirementDynamics.getCreateBy()));
            resultList.add(reqDynamicVo);
        }
        Page<ReqDynamicVo> reqDynamicVoPage = new Page<>(current, pageSize);
        BeanUtil.copyProperties(requirementDynamicsPage, reqDynamicVoPage);
        reqDynamicVoPage.setRecords(resultList);
        return reqDynamicVoPage;
    }


    @Override
    public List<RequirementVo> listByProjectIdAndOwnerId(Integer projectId, Integer ownerId) {
        if (ownerId == null) {
            return new ArrayList<>();
        }
        LambdaQueryWrapper<Requirements> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper
                .eq(Requirements::getProId, projectId)
                .eq(Requirements::getOwnerId, ownerId)
                .eq(Requirements::getDeleted, 0)
                .orderByAsc(Requirements::getPriority)
                .orderByAsc(Requirements::getEndTime)
                .orderByAsc(Requirements::getStartTime)
                .orderByAsc(Requirements::getStatus)
                .orderByAsc(Requirements::getCreateAt)
                .orderByAsc(Requirements::getUpdateAt)
                .orderByAsc(Requirements::getId);
        List<Requirements> requirementsList = requirementsMapper.selectList(queryWrapper);
        //获取附件数量
        List<Integer> reqIdList = requirementsList.stream().map(Requirements::getId).collect(Collectors.toList());
        List<AttachCount> attachCounts = new ArrayList<>();
        Map<Integer, AttachCount> reqAttachCountMap = new HashMap<>();
        if (!reqIdList.isEmpty()) {
            attachCounts = attachesMapper.countByReqIdList(reqIdList);
        }
        if (!attachCounts.isEmpty()) {
            attachCounts.forEach(attachCount -> reqAttachCountMap.put(attachCount.getTypeId(), attachCount));
        }
        //获取用户信息
        List<Integer> userIdList = requirementsList.stream()
                .flatMap(requirements -> Stream.of(requirements.getOwnerId(), requirements.getCreateBy(), requirements.getUpdateBy()))
                .filter(Objects::nonNull)
                .distinct()
                .collect(Collectors.toList());
        Map<Integer, UserVO> userVOMap = userService.listUserVoByIds(userIdList).stream()
                .collect(Collectors.toMap(UserVO::getId, userVO -> userVO));
        return requirementsList.stream().map(requirements -> {
            RequirementVo requirementVo = BeanUtil.copyProperties(requirements, RequirementVo.class);
            List<TaskVo> taskVoList = taskService.listByReqId(requirements.getId());
            requirementVo.setTaskVoList(taskVoList);
            requirementVo.setOwner(userVOMap.get(requirements.getOwnerId()));
            requirementVo.setCreator(userVOMap.get(requirements.getCreateBy()));
            requirementVo.setUpdater(userVOMap.get(requirements.getUpdateBy()));
            AttachCount attachCount = reqAttachCountMap.get(requirements.getId());
            requirementVo.setAttachCount(attachCount != null ? attachCount.getCount() : 0);
            return requirementVo;
        }).collect(Collectors.toList());
    }
}





